/*************************************************************************
	> File Name: CalcServer.cc
	> Author: H.M. Lau
	> Mail: hm.lau@outlook.com
	> Created Time: 2023/10/15 15:36
 ************************************************************************/

#include "TcpServer.hpp"
#include "Sock.hpp"
#include "Protocol.hpp"
#include "Daemon.hpp"
#include <vector>
#include <functional>
#include <pthread.h>

static void Usage(const std::string& proc)
{
    std::cout << "\nUsage:" << proc << " port\n" << std::endl;
}

static halil::Response calculatorHelper(const halil::Request& req)
{
    halil::Response resp(0, 0, req._x, req._y, req._op);
    switch (req._op) {
        case '+':
            resp._result = req._x + req._y;
            break;
        case '-':
            resp._result = req._x - req._y;
            break;
        case '*':
            resp._result = req._x * req._y;
            break;
        case '/':
            if (0 == req._y) {
                resp._code = 1;
            } else {
                resp._result = req._x / req._y;
            }
            break;
        case '%':
            if (0 == req._y) {
                resp._code = 2;
            } else {
                resp._result = req._x % req._y;
            }
            break;
        default:
            resp._code = 3;
            break;
    }
    return resp;
}

void calculator(int sock)
{
    std::string inbuffer;
    while (1) {
        if (!halil::Recv(sock, &inbuffer)) {
            break;
        }
        std::string package = halil::Decode(inbuffer);
        if (package.empty()) {
            continue;
        }
        logMessage(NORMAL, "%s", package.c_str());
        halil::Request req;
        req.Deserialized(package);
        halil::Response resp = calculatorHelper(req);
        std::string respString = resp.Serialize();
        respString = halil::Encode(respString);
        halil::Send(sock, respString);
    }
}

int main(int argc, char *argv[])
{
    if (argc != 2) {
        Usage(argv[0]);
        exit(1);
    }
    halil::Daemon();
    std::unique_ptr<halil::TcpServer> server(new halil::TcpServer(atoi(argv[1])));
    server->BindService(calculator);
    server->Start();
    return 0;
}
